"""战场模型"""

from typing import Dict, List, Optional, Tuple
from pydantic import BaseModel, Field
from .character import Character, CharacterType


class Position(BaseModel):
    """位置类"""
    x: int = Field(..., description="X坐标")
    y: int = Field(..., description="Y坐标")
    
    def __eq__(self, other):
        if isinstance(other, Position):
            return self.x == other.x and self.y == other.y
        return False
    
    def __hash__(self):
        return hash((self.x, self.y))


class Battlefield(BaseModel):
    """战场类 - 8x3网格布局（上方4x3为敌方，下方4x3为我方）"""
    
    width: int = Field(4, description="战场宽度")
    height: int = Field(6, description="战场高度（总共6行，上3行敌方，下3行我方）")
    
    # 角色位置映射
    player_positions: Dict[str, Position] = Field(default_factory=dict, description="玩家方位置")
    enemy_positions: Dict[str, Position] = Field(default_factory=dict, description="敌方位置")
    
    def __init__(self, **data):
        super().__init__(**data)
    
    def is_valid_position(self, x: int, y: int) -> bool:
        """检查位置是否有效"""
        return 0 <= x < self.width and 0 <= y < self.height
    
    def is_valid_position_for_team(self, x: int, y: int, character_type: CharacterType) -> bool:
        """检查位置对指定队伍是否有效"""
        if not self.is_valid_position(x, y):
            return False
        
        if character_type == CharacterType.ENEMY:
            # 敌方只能在上方区域 (y = 0, 1, 2)
            return 0 <= y <= 2
        else:
            # 我方只能在下方区域 (y = 3, 4, 5)
            return 3 <= y <= 5
    
    def is_position_occupied(self, x: int, y: int) -> bool:
        """检查位置是否被占用"""
        pos = Position(x=x, y=y)
        
        for position in self.player_positions.values():
            if position == pos:
                return True
                
        for position in self.enemy_positions.values():
            if position == pos:
                return True
                
        return False
    
    def place_character(self, character: Character, x: int, y: int) -> bool:
        """放置角色到指定位置"""
        if not self.is_valid_position_for_team(x, y, character.character_type):
            return False
            
        if self.is_position_occupied(x, y):
            return False
        
        # 移除角色的旧位置
        self.remove_character(character)
        
        # 设置新位置
        position = Position(x=x, y=y)
        if character.character_type == CharacterType.PLAYER:
            self.player_positions[character.id] = position
        else:
            self.enemy_positions[character.id] = position
            
        character.set_position(x, y)
        return True
    
    def remove_character(self, character: Character) -> bool:
        """移除角色"""
        removed = False
        
        if character.id in self.player_positions:
            del self.player_positions[character.id]
            removed = True
            
        if character.id in self.enemy_positions:
            del self.enemy_positions[character.id]
            removed = True
            
        if removed:
            character.position_x = None
            character.position_y = None
            
        return removed
    
    def get_character_at_position(self, x: int, y: int, characters: List[Character]) -> Optional[Character]:
        """获取指定位置的角色"""
        for character in characters:
            if character.position_x == x and character.position_y == y:
                return character
        return None
    
    def get_distance(self, pos1: Position, pos2: Position) -> int:
        """计算两个位置之间的曼哈顿距离"""
        return abs(pos1.x - pos2.x) + abs(pos1.y - pos2.y)
    
    def get_characters_in_range(self, center_x: int, center_y: int, range_size: int, 
                               characters: List[Character]) -> List[Character]:
        """获取范围内的角色"""
        targets = []
        center_pos = Position(x=center_x, y=center_y)
        
        for character in characters:
            if character.position_x is not None and character.position_y is not None:
                char_pos = Position(x=character.position_x, y=character.position_y)
                if self.get_distance(center_pos, char_pos) <= range_size:
                    targets.append(character)
                    
        return targets
    
    def get_adjacent_positions(self, x: int, y: int) -> List[Position]:
        """获取相邻位置"""
        adjacent = []
        directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]  # 上下左右
        
        for dx, dy in directions:
            new_x, new_y = x + dx, y + dy
            if self.is_valid_position(new_x, new_y):
                adjacent.append(Position(x=new_x, y=new_y))
                
        return adjacent
    
    def to_dict(self) -> Dict:
        """转换为字典"""
        return {
            "width": self.width,
            "height": self.height,
            "player_positions": {
                char_id: {"x": pos.x, "y": pos.y} 
                for char_id, pos in self.player_positions.items()
            },
            "enemy_positions": {
                char_id: {"x": pos.x, "y": pos.y} 
                for char_id, pos in self.enemy_positions.items()
            }
        }